﻿using SnShared;
using SnShared.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace SnClient
{
    public class CDMRestApi 
    {
        public ILogging Logger { get; set; }

        private static readonly string s_serviceUrl = Config.GetServiceUrl();
        private static string API_ROOT = "cdmmvc/api";
        private HttpClient m_httpCli = null;

        public CDMRestApi()
        {
            Logger = new Logging();
        }

        private void _ConnectRestClient()
        {
            _ConnectRestClientNoFiddler();
            //_ConnectRestClientFiddler();        
        }

        private void _ConnectRestClientNoFiddler()
        {
            if (m_httpCli != null)
            {
                return;
            }

            m_httpCli = new HttpClient();
            m_httpCli.BaseAddress = new Uri(s_serviceUrl);
            m_httpCli.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        }

        private void _ConnectRestClientFiddler()
        {
            if (m_httpCli != null)
            {
                return;
            }

            var clientHandler = new HttpClientHandler
            {
                UseCookies = true,
                UseDefaultCredentials = false,
                Proxy = new WebProxy("http://localhost:8888"),
                UseProxy = true,
                AutomaticDecompression = DecompressionMethods.GZip,
                AllowAutoRedirect = true,
                ClientCertificateOptions = ClientCertificateOption.Automatic
            };

            m_httpCli = new HttpClient(clientHandler);
            m_httpCli.BaseAddress = new Uri(s_serviceUrl);
            m_httpCli.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        }

        static private string GetApiPath( string objType )
        {
            return String.Format( "{0}/{1}", API_ROOT, objType );
        }

        private void VerifyResponse( HttpResponseMessage response )
        {
            Uri resultUri = response.Headers.Location;
            string absoluteUri = ( resultUri == null ? response.RequestMessage.RequestUri.AbsoluteUri : resultUri.AbsoluteUri );

            String msg2 = String.Format( "HTTP request to {0} ({1}), status code: {2}, reason: {3}.",
                s_serviceUrl,
                absoluteUri,
                ( int )response.StatusCode,
                response.ReasonPhrase );

            if ( response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Created )
            {
#if DEBUG
                Logger.LogOneEvent( LoggingEventId.EVENT_ID_HTTPREQUEST, EventLogEntryType.Information, msg2 );
#endif
                return;
            }

            if ( response.StatusCode == HttpStatusCode.BadRequest )
            {
                if ( response.Content != null )
                {
                    // RAError error = response.Content.ReadAsAsync<RAError>().Result;
                    absoluteUri = ( resultUri == null ? response.RequestMessage.RequestUri.AbsoluteUri : resultUri.AbsoluteUri );

                    String msg = String.Format( "HTTP request to {0} ({1}), status code: {2}, reason: {3}.",
                          s_serviceUrl,
                          absoluteUri,
                          ( int )response.StatusCode,
                          "" /* error.DisplayMessage() */ );

                    Logger.LogOneEvent( LoggingEventId.EVENT_ID_HTTPREQUEST, EventLogEntryType.Error, msg );

                    throw new ApplicationException( msg );
                }
            }

            Logger.LogOneEvent( LoggingEventId.EVENT_ID_HTTPREQUEST, EventLogEntryType.Error, msg2 );

            throw new ApplicationException( msg2 );
        }


        public List<SoftwarePackage> GetRevokedPackages()
        {
            List<SoftwarePackage> ret = null;

            try
            {
                //_ConnectRestClient();
                //_ConnectRestClientFiddler();

                HttpResponseMessage httpRsp = m_httpCli.GetAsync(GetApiPath("RevokedSoftwarePackages")).Result;
                
                VerifyResponse(httpRsp);

                ret = httpRsp.Content.ReadAsAsync<List<SoftwarePackage>>().Result;

            }
            catch ( Exception e )
            {
                Logger.LogException( e, LoggingEventId.EVENT_ID_EXCEPTION, "Failed to get revoked packages" );
                throw;
            }

            return ret;
        }
                
        public void PostPackage(AddPackage request)
        {
            try
            {
                _ConnectRestClient();
                //_ConnectRestClientFiddler();

                //
                // Create the request
                //                                
            
                string requestUri = GetApiPath("addpackages");
                HttpResponseMessage httpRsp = m_httpCli.PostAsJsonAsync(requestUri, request).Result;

                VerifyResponse(httpRsp);
   
            }
            catch (ApplicationException ae)
            {
                Logger.LogException(ae, LoggingEventId.EVENT_ID_REPORTINSTALLEDPACKAGES, "PostPackage");
                throw ae;
            }
            catch (Exception e)
            {
                Logger.LogException(e, LoggingEventId.EVENT_ID_REPORTINSTALLEDPACKAGES, "PostPackage");                
                throw e;
            }
        }

        public void RemovePackage(RemovePackage request)
        {
            try
            {
                _ConnectRestClient();
                //_ConnectRestClientFiddler();

                //
                // Create the request
                //                                

                string requestUri = GetApiPath("removepackages");
                HttpResponseMessage httpRsp = m_httpCli.PostAsJsonAsync(requestUri, request).Result;

                VerifyResponse(httpRsp);

            }
            catch (ApplicationException ae)
            {
                Logger.LogException(ae, LoggingEventId.EVENT_ID_REPORTINSTALLEDPACKAGES, "removepackages");
                throw ae;
            }
            catch (Exception e)
            {
                Logger.LogException(e, LoggingEventId.EVENT_ID_REPORTINSTALLEDPACKAGES, "removepackages");
                throw e;
            }
        }


        public void ResetDemo(SoftwarePackage package)
        {
            try
            {
                _ConnectRestClient();

                package.Revoked = false;

                //
                // Create the request
                //                                

                string requestUri = GetApiPath("demoreset");
                HttpResponseMessage httpRsp = m_httpCli.PutAsJsonAsync(requestUri + "/" + package.Id, package).Result;

                VerifyResponse(httpRsp);

            }
            catch (ApplicationException ae)
            {
                Logger.LogException(ae, LoggingEventId.EVENT_ID_REPORTINSTALLEDPACKAGES, "ResetDemo");
                throw ae;
            }
            catch (Exception e)
            {
                Logger.LogException(e, LoggingEventId.EVENT_ID_REPORTINSTALLEDPACKAGES, "ResetDemo");
                throw e;
            }
        }

    }
}
